﻿
using Xacml.Core;
using Xacml.Core.Interfaces;
using System;
using System.Collections;
using System.Xml;

namespace Xacml.Core.Policy
{
  public class PolicyElementReadWrite : XacmlElement, IHasTarget
  {
    private string _id = string.Empty;
    private string _description = string.Empty;
    private RuleCollectionReadWrite _rules = new RuleCollectionReadWrite();
    private ObligationCollectionReadWrite _obligations = new ObligationCollectionReadWrite();
    private ArrayList _combinerParameters = new ArrayList();
    private ArrayList _ruleCombinerParameters = new ArrayList();
    private IDictionary _variableDefinitions = (IDictionary) new Hashtable();
    private string _xpathVersion = string.Empty;
    private TargetElementReadWrite _target;
    private string _ruleCombiningAlgorithm;

    public virtual string Id
    {
      get
      {
        return this._id;
      }
      set
      {
        this._id = value;
      }
    }

    public virtual string Description
    {
      get
      {
        return this._description;
      }
      set
      {
        this._description = value;
      }
    }

    public virtual string RuleCombiningAlgorithm
    {
      get
      {
        return this._ruleCombiningAlgorithm;
      }
      set
      {
        this._ruleCombiningAlgorithm = value;
      }
    }

    public virtual TargetElementReadWrite Target
    {
      get
      {
        return this._target;
      }
      set
      {
        this._target = value;
      }
    }

    public virtual RuleCollectionReadWrite Rules
    {
      get
      {
        return this._rules;
      }
      set
      {
        this._rules = value;
      }
    }

    public virtual ObligationCollectionReadWrite Obligations
    {
      get
      {
        return this._obligations;
      }
      set
      {
        this._obligations = value;
      }
    }

    public virtual string XPathVersion
    {
      get
      {
        return this._xpathVersion;
      }
      set
      {
        this._xpathVersion = value;
      }
    }

    public virtual IDictionary VariableDefinitions
    {
      get
      {
        return this._variableDefinitions;
      }
      set
      {
        this._variableDefinitions = value;
      }
    }

    public virtual ArrayList CombinerParameters
    {
      get
      {
        return this._combinerParameters;
      }
      set
      {
        this._combinerParameters = value;
      }
    }

    public virtual ArrayList RuleCombinerParameters
    {
      get
      {
        return this._ruleCombinerParameters;
      }
      set
      {
        this._ruleCombinerParameters = value;
      }
    }

    public override bool IsReadOnly
    {
      get
      {
        return false;
      }
    }

    public PolicyElementReadWrite(string id, string description, TargetElementReadWrite target, RuleCollectionReadWrite rules, string ruleCombiningAlgorithm, ObligationCollectionReadWrite obligations, string xpathVersion, ArrayList combinerParameters, ArrayList ruleCombinerParameters, IDictionary variableDefinitions, XacmlVersion schemaVersion)
      : base(XacmlSchema.Policy, schemaVersion)
    {
      this._id = id;
      this._description = description;
      this._target = target;
      this._rules = rules;
      this._ruleCombiningAlgorithm = ruleCombiningAlgorithm;
      this._obligations = obligations;
      this._combinerParameters = combinerParameters;
      this._ruleCombinerParameters = ruleCombinerParameters;
      this._variableDefinitions = variableDefinitions;
      this._xpathVersion = xpathVersion;
    }

    public PolicyElementReadWrite(XmlReader reader, XacmlVersion schemaVersion)
      : base(XacmlSchema.Policy, schemaVersion)
    {
      if (reader.LocalName == "Policy" && this.ValidateSchema(reader, schemaVersion))
      {
        this._id = reader.GetAttribute("PolicyId");
        this._ruleCombiningAlgorithm = reader.GetAttribute("RuleCombiningAlgId");
        while (reader.Read())
        {
          switch (reader.LocalName)
          {
            case "Description":
              this._description = reader.ReadElementString();
              break;
            case "PolicyDefaults":
              if (reader.Read() && reader.Read())
              {
                if (reader.LocalName == "XPathVersion" && this.ValidateSchema(reader, schemaVersion))
                {
                  this._xpathVersion = reader.ReadElementString();
                  if (this._xpathVersion != null && this._xpathVersion.Length != 0 && this._xpathVersion != "http://www.w3.org/TR/1999/Rec-xpath-19991116")
                    throw new Exception(Resource.ResourceManager[Resource.MessageKey.exc_unsupported_xpath_version, new object[1]
                    {
                      (object) this._xpathVersion
                    }]);
                }
                reader.Read();
                break;
              }
              break;
            case "Target":
              this._target = new TargetElementReadWrite(reader, schemaVersion);
              break;
            case "Rule":
              this._rules.Add(new RuleElementReadWrite(reader, schemaVersion));
              break;
            case "Obligations":
              while (reader.Read())
              {
                switch (reader.LocalName)
                {
                  case "Obligation":
                    this._obligations.Add(new ObligationElementReadWrite(reader, schemaVersion));
                    break;
                }
                if (reader.LocalName == "Obligations" && reader.NodeType == XmlNodeType.EndElement)
                {
                  reader.Read();
                  break;
                }
              }
              break;
            case "CombinerParameters":
              while (reader.Read())
              {
                switch (reader.LocalName)
                {
                  case "CombinerParameter":
                    this._combinerParameters.Add((object) new CombinerParameterElement(reader, schemaVersion));
                    break;
                }
                if (reader.LocalName == "CombinerParameters" && reader.NodeType == XmlNodeType.EndElement)
                {
                  reader.Read();
                  break;
                }
              }
              break;
            case "RuleCombinerParameters":
              while (reader.Read())
              {
                switch (reader.LocalName)
                {
                  case "RuleCombinerParameterElement":
                    this._ruleCombinerParameters.Add((object) new RuleCombinerParameterElement(reader, schemaVersion));
                    break;
                }
                if (reader.LocalName == "RuleCombinerParameters" && reader.NodeType == XmlNodeType.EndElement)
                {
                  reader.Read();
                  break;
                }
              }
              break;
            case "VariableDefinition":
              VariableDefinitionElement definitionElement = new VariableDefinitionElement(reader, schemaVersion);
              this._variableDefinitions.Add((object) definitionElement.Id, (object) definitionElement);
              break;
          }
          if (reader.LocalName == "Policy" && reader.NodeType == XmlNodeType.EndElement)
            break;
        }
      }
      else
        throw new Exception(Resource.ResourceManager[Resource.MessageKey.exc_invalid_node_name, new object[1]
        {
          (object) reader.LocalName
        }]);
    }

    public void WriteDocument(XmlWriter writer, Hashtable namespaces)
    {
      writer.WriteStartElement("Policy");
      foreach (DictionaryEntry dictionaryEntry in namespaces)
        writer.WriteAttributeString("xmlns", dictionaryEntry.Key.ToString(), (string) null, dictionaryEntry.Value.ToString());
      writer.WriteAttributeString("PolicyId", this._id);
      writer.WriteAttributeString("RuleCombiningAlgId", this._ruleCombiningAlgorithm);
      if (this._description != string.Empty)
        writer.WriteElementString("Description", this._description);
      if (this._xpathVersion != string.Empty)
      {
        writer.WriteStartElement("PolicyDefaults");
        writer.WriteElementString("XPathVersion", this._xpathVersion);
        writer.WriteEndElement();
      }
      if (this._target != null)
        this._target.WriteDocument(writer);
      if (this._variableDefinitions != null)
      {
        foreach (DictionaryEntry dictionaryEntry in this._variableDefinitions)
          ((VariableDefinitionElement) dictionaryEntry.Value).WriteDocument(writer);
      }
      if (this._rules != null)
        this._rules.WriteDocument(writer);
      if (this._obligations != null)
        this._obligations.WriteDocument(writer);
      writer.WriteEndElement();
    }

    public void WriteDocument(XmlWriter writer)
    {
      writer.WriteStartElement("Policy");
      writer.WriteAttributeString("PolicyId", this._id);
      writer.WriteAttributeString("RuleCombiningAlgId", this._ruleCombiningAlgorithm);
      if (this._description != string.Empty)
        writer.WriteElementString("Description", this._description);
      if (this._xpathVersion != string.Empty)
      {
        writer.WriteStartElement("PolicyDefaults");
        writer.WriteElementString("XPathVersion", this._xpathVersion);
        writer.WriteEndElement();
      }
      if (this._target != null)
        this._target.WriteDocument(writer);
      if (this._variableDefinitions != null)
      {
        foreach (DictionaryEntry dictionaryEntry in this._variableDefinitions)
          ((VariableDefinitionElement) dictionaryEntry.Value).WriteDocument(writer);
      }
      if (this._rules != null)
        this._rules.WriteDocument(writer);
      if (this._obligations != null)
        this._obligations.WriteDocument(writer);
      writer.WriteEndElement();
    }
  }
}
